package com.bwie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.es.EsProd;
import com.bwie.mapper.TbProdAttaMapper;
import com.bwie.mapper.TbProdInfoMapper;
import com.bwie.pojo.TbProd;
import com.bwie.pojo.TbProdAtta;
import com.bwie.pojo.TbProdInfo;
import com.bwie.service.TbProdService;
import com.bwie.mapper.TbProdMapper;
import com.bwie.utils.R;
import com.bwie.utils.TokenUtils;
import com.bwie.vo.ProdPageVo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
* @author andy
* @description 针对表【tb_prod(商品表)】的数据库操作Service实现
* @createDate 2025-06-20 15:27:42
*/
@Service
public class TbProdServiceImpl extends ServiceImpl<TbProdMapper, TbProd>
    implements TbProdService{

    @Autowired
    TbProdMapper tbProdMapper;

    @Autowired
    TbProdInfoMapper tbProdInfoMapper;

    @Autowired
    TbProdAttaMapper tbProdAttaMapper;
    
    @Autowired
    HttpServletRequest request;

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public R getProdList(ProdPageVo prodPageVo) {
        //--1 构造分页参数
        Page<TbProd> page = new Page<>(prodPageVo.getPageNum(), prodPageVo.getPageSize());

        //--2 分页查询
//        Page<TbProd> tbProdPage = tbProdMapper.selectPage(page, null);
        Page<TbProd> tbProdPage = tbProdMapper.getProdList(page, prodPageVo);

        return R.ok().setData(tbProdPage);
    }

    @Override
    public R addProd(TbProd tbProd) {
        //--1 SPU和商品名称重复校验
        TbProd prod = tbProdMapper.selectOne(
                new QueryWrapper<TbProd>().lambda()
                        .eq(TbProd::getProdSpu, tbProd.getProdSpu())
                        .or()
                        .eq(TbProd::getProdName, tbProd.getProdName())
        );
        if(prod != null) {
            return R.error().setMsg("商品已存在");
        }

        //--2 设置审计字段
        String token = request.getHeader("token");
        if(token == null) {
            return R.error().setMsg("请先登录");
        }
        String userName = TokenUtils.getUserName(token);

        tbProd.setCreateBy(userName);
        tbProd.setCreateTime(new Date());

        //--3 添加商品
        tbProdMapper.insert(tbProd);

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R addProdAtta(TbProdAtta tbProdAtta) {
        //--1 判断商品是存在
        TbProd tbProd = tbProdMapper.selectById(tbProdAtta.getProdId());
        if(tbProd == null) {
            return R.error().setMsg("商品不存在");
        }

        //--2 删除原有附件：根据商品的ID进行删除
        tbProdAttaMapper.delete(
                new QueryWrapper<TbProdAtta>().lambda().eq(TbProdAtta::getProdId, tbProdAtta.getProdId())
        );

        //--3 添加附件
        tbProdAttaMapper.insert(tbProdAtta);

        return R.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteBatchProd(List<Integer> ids) {
        //--1 批量删除商品
        tbProdMapper.deleteBatchIds(ids);

        //--2 批量删除商品附件
        // delete from tb_prod_atta where prod_id in (1,2,3)
        tbProdAttaMapper.delete(
                new QueryWrapper<TbProdAtta>().lambda().in(TbProdAtta::getProdId, ids)
        );

        return R.ok();
    }

    @Override
    public R deleteProd(Integer prodId) {
        //--1 判断商品是否存在
        TbProd tbProd = tbProdMapper.selectById(prodId);
        if(tbProd == null) {
            return R.error().setMsg("商品不存在");
        }

        //--2 删除商品
        tbProdMapper.deleteById(prodId);

        return R.ok();
    }

    @Override
    public R getProdInfoList() {

        List<TbProdInfo> list = tbProdInfoMapper.selectList(null);

        return R.ok().setData(list);
    }

    @Override
    public R getProdFromEs(ProdPageVo prodPageVo) {
        //--1 构造分页参数
        // MybatisPlus 分页是从1开始计数的
        // ES 分页是从0开始计数的
        Integer pageNum = 0;
        if(prodPageVo.getPageNum() > 0) {
            pageNum = prodPageVo.getPageNum() - 1;
        }
        PageRequest pageRequest = PageRequest.of(pageNum, prodPageVo.getPageSize());

        //--2 构造多条件查询
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        // 商品名称搜索
        // matchQuery： 分词查找
        // termQuery： 不分词查找
        // must: and 条件之间是且的关系
        // should: or 条件之间是或的关系
        if(StringUtils.isNotEmpty(prodPageVo.getKeyWord())) {
            boolQueryBuilder.should(QueryBuilders.matchQuery("prodName", prodPageVo.getKeyWord()));
            boolQueryBuilder.should(QueryBuilders.matchQuery("brandName", prodPageVo.getKeyWord()));
        }
        // 状态搜索
        if(prodPageVo.getStatus() != null) {
            boolQueryBuilder.must(QueryBuilders.termQuery("prodStatus", prodPageVo.getStatus()));
        }
        // 根据价格区间查询
        if(false) {
//            boolQueryBuilder.must(QueryBuilders.rangeQuery("price").from(prodPageVo.getMinPrice()).to(prodPageVo.getMaxPrice()));
//            boolQueryBuilder.must(QueryBuilders.rangeQuery("price").gte(prodPageVo.getMinPrice()).lte(prodPageVo.getMaxPrice()));
        }

        // 时间区间查询
        if(StringUtils.isNotEmpty(prodPageVo.getBeginTime()) && StringUtils.isNotEmpty(prodPageVo.getEndTime())) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime")
                    .format("yyyy-MM-dd HH:mm:ss")
                    .timeZone("GMT+8")
                    .from(prodPageVo.getBeginTime())
                    .to(prodPageVo.getEndTime()));
        }

        // 添加高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("prodName")
                .field("brandName")
                .preTags("<font color='red'>")
                .postTags("</font>");

        // 排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("prodId").order(SortOrder.ASC);


        //--3 查询
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder)
                .withPageable(pageRequest)                  // 分页
                .withSort(sortBuilder)                      // 排序
                .withHighlightBuilder(highlightBuilder);    // 高亮
        SearchHits<EsProd> searchHits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsProd.class);

        //--4 读取数据
        long total = searchHits.getTotalHits();
        ArrayList<EsProd> records = new ArrayList<>();

        for (SearchHit<EsProd> searchHit : searchHits.getSearchHits()) {
            EsProd esProd = searchHit.getContent();

            // 读取高亮信息
            List<String> prodNames = searchHit.getHighlightField("prodName");
            if(prodNames!=null && prodNames.size()>0) {
                esProd.setProdName(prodNames.get(0));
            }

            List<String> brandNames = searchHit.getHighlightField("brandName");
            if(brandNames!=null && brandNames.size()>0) {
                esProd.setBrandName(brandNames.get(0));
            }

            records.add(esProd);
        }

        //--5 返回数据
        HashMap<String, Object> map = new HashMap<>(2);
        map.put("total", total);
        map.put("records", records);

        return R.ok().setData(map);
    }
}




